home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / X11 / gasket / gasket.c next >
C/C++ Source or Header  |  1995-05-25  |  11KB  |  449 lines

  1. /*
  2.  * gasket - a general serpinski gasket generator
  3.  * usage: gasket [-MCRWiu][-f file][-n numpts][-N numgen][-h high][-w wide]
  4.  * 
  5.  * Originally by Cloister Bell (cloister@milton.u.washington.edu).
  6.  * Rewritten by Ron Record (rr@sco.com).
  7.  */
  8.  
  9. #include <X11/Xlib.h>
  10. #include <X11/Xutil.h>
  11. #include <X11/keysym.h>
  12. #include <bool.h>
  13. #include <math.h>
  14. #include <stdio.h>
  15. #include <dirent.h>
  16. #include <values.h>
  17.  
  18. #define MINCOLOR 2
  19. #define MAXCOLOR 64
  20. #define MAXVERT 16
  21. #define SAVEDIR "/usr/bin/X11/lib/gasket"
  22.  
  23. #ifdef M_SYSV
  24. #include <bool.h>
  25. #define random rand
  26. #define srandom srand
  27. #endif
  28.  
  29. char windowname[]= "Serpinski Gaskets";
  30.  
  31. Display *display;
  32. Window window;
  33. GC gc[MAXCOLOR];
  34. int Colors;
  35. int fflag=0, iflag=0, rflag=0, Cflag=0, Mflag=0, Rflag=0, Qflag=1, Wflag=0;
  36. char *infile;
  37. char foofile[1] = ".";
  38. int   x_coord[20], y_coord[20];
  39. int   allowed[20][20], n;
  40. int   x, y, prev;
  41. int   maxgen=MAXINT, numgen=0, numpts=10000, skipnum=0;
  42. int   width=500, height=500;
  43. double   x_weight=2, y_weight=2;
  44.  
  45. extern long random();
  46.  
  47. draw()
  48. {    
  49.   int   next;
  50.   int    i, j;
  51.   int   good;
  52.  
  53.   for(i=0; i < numpts; i++)
  54.     {
  55.       good = 0;
  56.       while (!good)
  57.         {
  58.       next = ((int)(random()) % n) + 1;
  59.       good = allowed[prev][next];
  60.         }
  61.       x = (int)((double)(x + x_coord[next]) / x_weight);
  62.       y = (int)((double)(y + y_coord[next]) / y_weight);
  63.       XDrawPoint(display, window, gc[MINCOLOR + prev], x, y);
  64.       prev = next;
  65.     }
  66.   if (++numgen > maxgen) {
  67.     if ((!Cflag) && (!iflag))
  68.        Qflag=0;
  69.     return(0);
  70.   }
  71.   return(1);
  72. }
  73.  
  74. main(argc,argv)
  75.      int argc;
  76.      char **argv;
  77. {
  78.   XEvent event;
  79.   XSizeHints hint;
  80.   int screen;
  81.   unsigned long foreground, background;
  82.   int i, j;
  83.   char text[10];
  84.   int done, interval;
  85.   int D=0, update=50;
  86.   DIR *dir_pt;
  87.   struct dirent *dp;
  88.   
  89.   display = XOpenDisplay("");
  90.   screen = DefaultScreen(display);
  91.   background = BlackPixel(display, screen);
  92.   Colors = XDisplayCells(display, screen);
  93.   Parseargs(argc, argv);
  94.   D = (int) DisplayPlanes(display,screen);
  95.   if (D > 1)
  96.     foreground = MINCOLOR;
  97.   else {
  98.     Mflag=1;
  99.     foreground = WhitePixel(display,screen);
  100.   }
  101.   hint.x = 300;
  102.   hint.y = 400;
  103.   hint.width = width;
  104.   hint.height = height;
  105.   hint.flags = PPosition | PSize;
  106.   init();
  107.   window = XCreateSimpleWindow(display, DefaultRootWindow(display),
  108.                    hint.x, hint.y, hint.width, hint.height,
  109.                    5, foreground, background);
  110.   XSetStandardProperties(display, window, windowname, windowname, None,
  111.              argv, argc, &hint);
  112.   for (i=0; i<MAXCOLOR; i++) {
  113.       gc[i] = XCreateGC(display, window, 0, 0);
  114.       XSetBackground(display, gc[i], background);
  115.     if (Mflag)
  116.           XSetForeground(display, gc[i], foreground);
  117.     else
  118.           XSetForeground(display, gc[i], (i%(Colors-1))+1);
  119.   }
  120.   XSelectInput(display, window, KeyPressMask | ButtonPressMask | ExposureMask);
  121.   XMapRaised(display, window);
  122.   interval=0;
  123.   if (Cflag) {
  124.       dir_pt = opendir(SAVEDIR);
  125.       while (foofile[0] == '.') {
  126.         dp = readdir(dir_pt);
  127.         foofile[0] = dp->d_name[0];
  128.       }
  129.       if (dp == NULL) {
  130.     perror("gasket: ");
  131.     fprintf(stderr,"No files in save directory\n");
  132.     exit(3);
  133.       }
  134.       getparams(dp);
  135.   }
  136.   if (rflag)
  137.       restparams();
  138.   prev = (random() % n) + 1;
  139.   nodraw();
  140.   while (Qflag) {
  141.     while (draw())
  142.     {   
  143.      if ((interval = XEventsQueued(display, QueuedAfterFlush)) > 0);
  144.     while (interval--) {
  145.           XNextEvent(display, &event);
  146.           switch(event.type) 
  147.             {
  148.             case KeyPress:
  149.           switch (XLookupKeysym(&event, 0)) {
  150.             case XK_C:
  151.             case XK_c:
  152.             XClearArea(display, window, 0, 0, 0, 0, TRUE);
  153.             break;
  154.             case XK_Q:
  155.             case XK_q:
  156.             case XK_Cancel:
  157.             case XK_Break:
  158.               bye();
  159.             case XK_f:
  160.             case XK_F:
  161.             case XK_w:
  162.             case XK_W:
  163.             saveparams();
  164.             break;
  165.           }
  166.           break;
  167.             case Expose:
  168.           break;
  169.             case ButtonPress:
  170.           switch(event.xbutton.button) 
  171.             {
  172.             case Button1:
  173.           XClearArea(display, window, 0, 0, 0, 0, TRUE);
  174.               break;
  175.             case Button2:
  176.           saveparams();
  177.               break;
  178.             case Button3:
  179.               bye();
  180.               break;
  181.             }
  182.           break;
  183.             }
  184.         }
  185.     }
  186.     if (Cflag) {
  187.       dp = readdir(dir_pt);
  188.       if (dp == NULL)
  189.     if (iflag) {
  190.         closedir(dir_pt);
  191.         foofile[0] = '.';
  192.               dir_pt = opendir(SAVEDIR);
  193.               while (foofile[0] == '.') {
  194.                 dp = readdir(dir_pt);
  195.                 foofile[0] = dp->d_name[0];
  196.               }
  197.               if (dp == NULL) {
  198.             perror("gasket: ");
  199.             fprintf(stderr,"No files in save directory\n");
  200.             exit(3);
  201.               }
  202.               getparams(dp);
  203.     }
  204.     else
  205.         Qflag=0;
  206.       else
  207.           getparams(dp);
  208.     }
  209.     else if (Rflag && iflag) {
  210.     randparams();
  211.     XClearArea(display, window, 0, 0, 0, 0, TRUE);
  212.     numgen=0;
  213.     }
  214.     else if (!iflag)
  215.     Qflag=0;
  216.     x = x_coord[1];
  217.     y = y_coord[1];
  218.     prev = (random() % n) + 1;
  219.     nodraw();
  220.   }
  221. }
  222.  
  223. Parseargs(ac, av)
  224. int ac;
  225. char **av;
  226. {
  227.     register int c;
  228.     extern int optind;
  229.     extern char *optarg;
  230.     extern double atof();
  231.  
  232.     while ((c = getopt(ac, av, "N:MCFRS:X:Y:Wf:h:in:ruw:")) != EOF) {
  233.         switch (c) {
  234.         case 'C':    Cflag++; break;
  235.         case 'F':    width = (int)DisplayWidth(display,0) - 20; 
  236.                 height = (int)DisplayHeight(display,0) - 30;
  237.                 break;
  238.         case 'M':    Mflag++; break;
  239.         case 'N':    maxgen = atoi(optarg); break;
  240.         case 'R':    Rflag++; break;
  241.         case 'S':    skipnum = atoi(optarg); break;
  242.         case 'W':    Wflag++; break;
  243.         case 'X':    x_weight = atof(optarg); break;
  244.         case 'Y':    y_weight = atof(optarg); break;
  245.         case 'f':    infile = optarg; fflag++; break;
  246.         case 'h':    height = atoi(optarg); break;
  247.         case 'i':    iflag++; break;
  248.         case 'n':    numpts = atoi(optarg); break;
  249.         case 'r':    rflag++; break;
  250.         case 'w':    width = atoi(optarg); break;
  251.         case 'u':
  252.         case '?':    usage(); break;
  253.         }
  254.     }
  255.     if ((Cflag && rflag) || (Cflag && fflag) || (rflag && fflag)) {
  256.         fprintf(stderr,"Only one of -C, -f, -r allowed\n");
  257.         usage();
  258.     }
  259. }
  260.  
  261. init() {
  262.  
  263.   FILE *file;
  264.   static int i, j; 
  265.   char *tempfile;
  266.  
  267.   srandom((int)time(0));
  268.   srand48((int)time(0));
  269.   if (fflag) {
  270.       if (infile[0] == '$') {
  271.     tempfile = (char *)strdup(&infile[1]);
  272.     strcpy(infile, SAVEDIR);
  273.     strcat(infile, tempfile);
  274.       }
  275.       file = fopen(infile, "r");
  276.       if (!file) {
  277.     perror("gasket: ");
  278.     fprintf(stderr,"Failed to open %s\n",infile);
  279.     exit(2);
  280.       }
  281.       fscanf(file,"%d",&n);
  282.       for (i = 0; i < n; i++)
  283.     fscanf(file, "%d %d",&x_coord[i+1],&y_coord[i+1]);
  284.       for (i = 0; i < n; i++)
  285.     for (j = 0; j < n; j++)
  286.       fscanf(file,"%d", &allowed[i+1][j+1]);
  287.       fclose(file);
  288.   }
  289.   else if ((!Cflag) && (!Rflag) && (!rflag)) {
  290.       printf("enter number of vertices: ");
  291.       scanf("%d",&n);
  292.       printf("enter co-ordinates for each vertex, as x y pairs:\n");
  293.       for(i=0; i < n; i++)
  294.     scanf("%d %d",&x_coord[i+1],&y_coord[i+1]);
  295.       printf("enter next-allowed matrix (0's and 1's):\n");
  296.       for (i=0; i < n; i++)
  297.     for (j=0; j < n; j++)
  298.       scanf("%d", &allowed[i+1][j+1]);
  299.   }
  300.   else if (Rflag)
  301.     randparams();
  302.   x = x_coord[1];
  303.   y = y_coord[1];
  304. }
  305.  
  306. nodraw()
  307. {
  308.   static int next, good;
  309.   static int i;
  310.  
  311.   for(i=0; i < skipnum; i++)
  312.     {
  313.       good = 0;
  314.       while (!good)
  315.         {
  316.       next = ((int)(random()) % n) + 1;
  317.       good = allowed[prev][next];
  318.         }
  319.       x = (int)((x + x_coord[next]) / 2);
  320.       y = (int)((y + y_coord[next]) / 2);
  321.       prev = next;
  322.     }
  323. }
  324.  
  325. getparams(dp)
  326. struct dirent *dp;
  327. {
  328.     char infile[128];
  329.       FILE *file;
  330.       static int i, j;
  331.  
  332.     strcpy(infile, SAVEDIR);
  333.     strcat(infile, "/");
  334.     strcat(infile, dp->d_name);
  335.           file = fopen(infile, "r");
  336.           if (!file) {
  337.         perror("gasket: ");
  338.         fprintf(stderr,"Failed to open %s\n",infile);
  339.         exit(2);
  340.         }
  341.         fscanf(file,"%d",&n);
  342.         for (i = 0; i < n; i++)
  343.       fscanf(file, "%d %d",&x_coord[i+1],&y_coord[i+1]);
  344.         for (i = 0; i < n; i++)
  345.       for (j = 0; j < n; j++)
  346.         fscanf(file,"%d", &allowed[i+1][j+1]);
  347.         fclose(file);
  348.     XClearArea(display, window, 0, 0, 0, 0, TRUE);
  349.     numgen=0;
  350. }
  351.  
  352. restparams()
  353. {
  354.     FILE *sf;
  355.     char Savefile[128];
  356.     static int i, j;
  357.  
  358.     strcpy(Savefile, getenv("HOME"));
  359.     strcat(Savefile, "/.gasket");
  360.     sf = fopen(Savefile, "r");
  361.     if (!sf) {perror("gasket: ~/.gasket"); exit(1); }
  362.         fscanf(sf,"%d",&n);
  363.         for (i = 0; i < n; i++)
  364.       fscanf(sf, "%d %d",&x_coord[i+1],&y_coord[i+1]);
  365.         for (i = 0; i < n; i++)
  366.       for (j = 0; j < n; j++)
  367.         fscanf(sf,"%d", &allowed[i+1][j+1]);
  368.         fclose(sf);
  369. }
  370.  
  371. saveparams()
  372. {
  373.     FILE *sf;
  374.     char Savefile[128];
  375.     static int i, j;
  376.  
  377.     strcpy(Savefile, getenv("HOME"));
  378.     strcat(Savefile, "/.gasket");
  379.     sf = fopen(Savefile, "w");
  380.     if (!sf) {perror("gasket: ~/.gasket"); exit(1); }
  381.     fprintf(sf,"%d\n",n);
  382.     for (i=0; i<n; i++)
  383.         fprintf(sf,"%d %d\n", x_coord[i+1], y_coord[i+1]);
  384.     for (i=0; i<n; i++) {
  385.         for (j=0; j<n; j++)
  386.         fprintf(sf,"%d ", allowed[i+1][j+1]);
  387.         fprintf(sf,"\n");
  388.     }
  389.     fclose(sf);
  390. }
  391.  
  392. randparams()
  393. {
  394.         /*
  395.      * Compute polar coordinates with 0 < r < (width/2) and theta in 
  396.          * successive pie slices of angular width 2*PI/n.
  397.          * Then change back to cartesian coordinates via
  398.          * x=r*cos(theta) and y=r*sin(theta)
  399.          */
  400.     static int i, j, r, good, row;
  401.     static double theta, tpiovern;
  402.     extern double sin(), cos(), drand48();
  403.  
  404.     n = (random() % MAXVERT) + 4;
  405.     for (i=0; i<n; i++) {
  406.         r = random() % (width/2);
  407.         tpiovern = (2.0 * M_PI) / (double)n;
  408.         theta = (drand48() * tpiovern) + ((double)i * tpiovern);
  409.         x_coord[i+1] = (int)((double)r * cos(theta)) + (width/2);
  410.         y_coord[i+1] = (int)((double)r * sin(theta)) + (height/2);
  411.     }
  412.     good = 0;
  413.     while (!good) {
  414.       good = 1;
  415.           for (i=0; i < n; i++) {
  416.         row=0;
  417.         for (j=0; j < n; j++) {
  418.         allowed[i+1][j+1] = (random() % 3) % 2; /* 1/3 chance of a 1 */
  419.         if ((allowed[i+1][j+1]) && ((i+1) != (j+1))) row=1;
  420.         }
  421.         good = good && row; /* force at least one 1 in each matrix row */
  422.       }
  423.     }
  424.     if (Wflag)
  425.         saveparams();
  426. }
  427.  
  428. usage()
  429. {
  430.     fprintf(stderr,"gasket [-MCRWiru][-f file][-n numpts][-N numgen]\n");
  431.     fprintf(stderr,"\twhere:\t-M indicates Monochrome\n");
  432.     fprintf(stderr,"\t\t-C indicates cycle thru saved data files\n");
  433.     fprintf(stderr,"\t\t-R indicates pick parameters at random\n");
  434.     fprintf(stderr,"\t\t-W indicates write out parameters each run\n");
  435.     fprintf(stderr,"\t\t-i indicates infinite mode\n");
  436.     fprintf(stderr,"\t\t-r recalls saved parameters in $HOME/.gasket\n");
  437.     fprintf(stderr,"\t\t-u displays this message\n");
  438.     fprintf(stderr,"\t\tnumpts is the number of points per color\n");
  439.     fprintf(stderr,"\t\tnumgen is the number of color changes\n");
  440.     exit(1);
  441. }
  442.  
  443. bye()
  444. {
  445.   XDestroyWindow(display, window);
  446.   XCloseDisplay(display);
  447.   exit(0);
  448. }
  449.